/**
 * <p>SystemName: WLBSNS</p>
 * <p>Description: </p> 
 * <p>Copyright: Copyright (c) 2013</p> 
 * <p>Company: </p> 
 * @author Theron 
 * @date 2013年11月7日 下午6:27:44 
 * @version V1.0 
 */
package com.wlbsns.framework.db;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.wlbsns.framework.exception.SystemException;
import com.wlbsns.framework.tools.StrUtils;

/**
 * description：数据库操作帮助类
 * @author Theron
 * @date 2013年11月7日 下午6:20:44
 */
public final class DBHelper {

	// 声明变量
	private Connection conn = null;
	private PreparedStatement ps = null;
	private ResultSet rs = null;

	/**
	 * 通过构造函数获取连接对象
	 * 
	 * @throws SQLException
	 */
	public DBHelper() {
		conn = JdbcUtils.getConnection();
	}

	/**
	 * 
	 * function: 更新数据表
	 * description: 用于对数据库表增加、删除、跟新后的数据表更新，可用于对数据表增删改数据
	 * @date 2013年11月7日 下午11:59:02
	 * @param sql 数据库操作语句
	 * @param objs 数据库语句的参数集合
	 * @return num 数据表更新的记录数
	 * @throws SystemException
	 */
	public int updateObjectInfo(String sql, Object... objs)
			throws SystemException {
		int num = 0;
		try {
			// 操作数据库
			ps = conn.prepareStatement(sql);

			// 参数元数据
			ParameterMetaData param = ps.getParameterMetaData();

			if (objs != null && objs.length > 0) {
				// 循环为上下文对象赋值
				for (int i = 0; i < param.getParameterCount(); i++) {
					ps.setObject(i + 1, objs[i]);
				}
			} else {
				throw new SystemException("参数不匹配");
			}

			// 执行sql语句
			num = ps.executeUpdate();

		} catch (SQLException e) {
			e.printStackTrace();
			throw new SystemException("数据库操作失败",e);
		}
		return num;
	}


	/**
	 * 
	 * function: 通过sql查询一个对象
	 * description: 通过sql语句查询数据库表中数据，并返回一条数据 
	 * @date 2013年11月8日 上午12:21:57
	 * @param sql
	 * @param clazz 实体类对象
	 * @return T 
	 */
	public <T> T queryObjectInfo(String sql, Class<T> clazz) throws SystemException  {
		T t = null;
		try {
			ps = conn.prepareStatement(sql);
			rs = ps.executeQuery();

			// 得到结果集元数据
			ResultSetMetaData rsmd = rs.getMetaData();

			// 遍历Object中的所有共有方法
			Method[] methods = clazz.getDeclaredMethods();

			// 遍历结果集
			if (rs.next()) {
				t = clazz.newInstance();// 初始化对象
				for (int i = 0; i < rsmd.getColumnCount(); i++) {

					// 得到字段名
					String colName = rsmd.getColumnLabel(i + 1);

					// 通过字段名拼接出方法名
					String methodName = "set"
							+ StrUtils.strToUpperCaseOfIndex(colName,0);
					for (Method method : methods) {
						if (methodName.equals(method.getName())) {
							method.invoke(t, rs.getObject(colName));
						}
					}
				}
			}
		} catch (SQLException e) {
			throw new SystemException("数据库操作失败",e);
		} catch (InstantiationException e) {
			throw new SystemException("对象初始化失败" , e);
		} catch (IllegalAccessException e) {
			throw new SystemException("指定的类或初始化程序不可访问" , e);
		} catch (IllegalArgumentException e) {
			throw new SystemException("目标方法参数异常",e);
		} catch (InvocationTargetException e) {
			throw new SystemException("目标方法调用失败", e);
		}
		return t;
	}

	/**
	 * 
	 * function: 
	 * description: 通过指定的条件查询数据库中的数据，并返回一条数据
	 * @date 2013年11月8日 上午12:38:38
	 * @param sql
	 * @param clazz
	 * @param objs
	 * @return
	 */
	public <T> T queryObjectByCondition(String sql, Class<T> clazz,
			Object... objs) throws SystemException {
		T t = null;
		try {
			ps = conn.prepareStatement(sql);

			// 判断参数是否为空
			if (objs.length > 0) {
				for (int i = 0; i < objs.length; i++) {

					// 为上下文对象赋值
					ps.setObject(i + 1, objs[i]);
				}
			} else {
				throw new SystemException("查询条件参数列表为！");
			}

			// 执行查询，返回结果集rs
			rs = ps.executeQuery();

			// 得到结果集元数据
			ResultSetMetaData rsmd = rs.getMetaData();

			// 获取对象clazz的共有方法
			Method[] methods = clazz.getDeclaredMethods();

			// 判断rs中是否有值
			if (rs.next()) {
				t = clazz.newInstance();// 实例化对象
				for (int i = 0; i < rsmd.getColumnCount(); i++) {
					String colName = rsmd.getColumnLabel(i + 1);// 得到字段名

					// 拼接对象set方法,将字段的第一个字符转换成大写
					String methodName = "set"
							+ StrUtils.strToUpperCaseOfIndex(colName,0);

					// 遍历所有方法
					for (Method method : methods) {
						if (methodName.equals(method.getName())) {
							method.invoke(t, rs.getObject(colName));
						}
					}
				}
			}
		} catch (SQLException e) {
			throw new SystemException("数据库操作失败",e);
		} catch (InstantiationException e) {
			throw new SystemException("对象初始化失败" , e);
		} catch (IllegalAccessException e) {
			throw new SystemException("指定的类或初始化程序不可访问" , e);
		} catch (IllegalArgumentException e) {
			throw new SystemException("目标方法参数异常",e);
		} catch (InvocationTargetException e) {
			throw new SystemException("目标方法调用失败", e);
		}
		return t;
	}

	/**
	 * 
	 * function: 
	 * description: 通过对象查询数据库中的所有记录并返回一个该对象的list集合
	 * @date 2013年11月8日 上午12:47:11
	 * @param clazz
	 * @return list
	 */
	public <T> List<T> queryObjects(Class<T> clazz) throws SystemException {
		List<T> lists = new ArrayList<T>(); // 创建一个集合存储查询数据
		T t = null;
		try {
			// 构建sql语句
			String sql = "select * from tb_" + clazz.getSimpleName();
			
			// 得到上下文对象
			ps = conn.prepareStatement(sql);
			rs = ps.executeQuery();// 执行查询，返回结果集

			// 得到结果集元数据
			ResultSetMetaData rsmd = rs.getMetaData();

			// 得到对象clazz中公有方法
			Method[] methods = clazz.getDeclaredMethods();

			// 遍历结果集
			while (rs.next()) {// 行
				t = clazz.newInstance();
				for (int i = 0; i < rsmd.getColumnCount(); i++) {// 列
					String colName = rsmd.getColumnLabel(i + 1);
					String methodName = "set"
							+ StrUtils.strToUpperCaseOfIndex(colName,0);

					// 遍历对象中的方法
					for (Method method : methods) {
						if (methodName.equals(method.getName())) {
							method.invoke(t, rs.getObject(colName));
						}
					}
				}
				lists.add(t);
			}
		} catch (SQLException e) {
			throw new SystemException("数据库操作失败",e);
		} catch (InstantiationException e) {
			throw new SystemException("对象初始化失败" , e);
		} catch (IllegalAccessException e) {
			throw new SystemException("指定的类或初始化程序不可访问" , e);
		} catch (IllegalArgumentException e) {
			throw new SystemException("目标方法参数异常",e);
		} catch (InvocationTargetException e) {
			throw new SystemException("目标方法调用失败", e);
		}
		return lists;
	}
}
